from collections.abc import Mapping
from typing import Iterable
import yaml
from rule import Mapable, Rule, Condition, Eq

DB_NAME = "sqlalchemy"
DB_URL = "mysql+pymysql://root:123456@localhost/shfe"
CRON_EXPRESS = "* */1 * * *"  # 默认一分钟一次


class Conf(Mapping, Mapable):

    def __init__(self):
        self._dict = dict()

    def __len__(self):
        return len(self._dict)

    def __iter__(self):
        return iter(self._dict)

    def __getitem__(self, item):
        return self[item]

    def to_map(self) -> Mapping:
        return self._dict

    def add_bool(self, k, v: bool):
        if not isinstance(v, bool):
            return
        self._dict[k] = v

    def add_int(self, k, v: int):
        if not isinstance(v, int):
            return
        self._dict[k] = v

    def add_str(self, k, v: str):
        if not isinstance(v, str):
            return
        self._dict[k] = v

    def add_float(self, k, v: float):
        if not isinstance(v, float):
            return
        self._dict[k] = v

    def add_obj(self, k, v: Iterable):
        def check(vv):
            if isinstance(vv, (str, int, float, bool)):
                return vv
            if isinstance(vv, Mapable):
                vv = vv.to_map()
            if isinstance(vv, Iterable):
                if isinstance(vv, Mapping):
                    replaced = {}
                    for i, j in vv.items():
                        rr = check(j)
                        if rr is None:
                            return
                        replaced.update({i: rr})
                    replaced.update(vv)
                    return replaced
                else:
                    replaced = list()
                    for vvv in vv:
                        lr = check(vvv)
                        if lr is None:
                            return
                        replaced.append(lr)
                    return replaced
            return None

        r = check(v)
        if r:
            self._dict[k] = r

    def remove(self, k):
        del self._dict[k]

    def clear(self):
        self._dict.clear()

    def __str__(self):
        return str(self.to_map())

    __repr__ = __str__


class Serializable:

    @staticmethod
    def dump(conf: Conf, file: str):
        pass

    @staticmethod
    def load(file) -> Conf:
        pass


class YamlConf(Serializable):

    @staticmethod
    def dump(c: Conf, file: str):
        with open(file, "w", encoding="utf-8") as fp:
            yaml.safe_dump(c.to_map(), fp, allow_unicode=True, sort_keys=False)

    @staticmethod
    def load(file) -> Conf:
        with open(file, "r", encoding="utf-8") as fp:
            return yaml.safe_load(fp)


def generate_conf():
    conf = Conf()
    rule = Rule(["*"], "&")  # 默认不过滤任何数据
    conf.add_obj("sys", {"db_name": DB_NAME, "db_url": DB_URL, "cron": CRON_EXPRESS})
    conf.add_obj("rules", [rule])
    YamlConf.dump(conf, "shfe.yaml")
